
package top.codef.secure.handlers;
import java.io.IOException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;

import com.fasterxml.jackson.databind.ObjectMapper;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import top.codef.secure.config.interfaces.LoginFailedDecorator;
import top.codef.secure.exceptions.CerberusAuthenticationException;
import top.codef.secure.pojomodel.SecureResponseEnum;
import top.codef.secure.properties.CerberusLoginReturnProperties;

public class CerberusLoginFailedHandler implements AuthenticationFailureHandler {

	private final ObjectMapper objectMapper;

	private final static String CONTENT_TYPE = "application/json; charset=utf-8";

	private final CerberusLoginReturnProperties cerberusLoginReturnProperties;

	private final LoginFailedDecorator loginFailedDecorator;

	private final static Log logger = LogFactory.getLog(CerberusLoginFailedHandler.class);

	public CerberusLoginFailedHandler(ObjectMapper objectMapper,
			CerberusLoginReturnProperties cerberusLoginReturnProperties) {
		this.objectMapper = objectMapper;
		this.cerberusLoginReturnProperties = cerberusLoginReturnProperties;
		this.loginFailedDecorator = (request, response, exception) -> {
			logger.debug("login failed:" + exception.getMessage());
			return null;
		};
	}

	public CerberusLoginFailedHandler(ObjectMapper objectMapper,
			CerberusLoginReturnProperties cerberusLoginReturnProperties, LoginFailedDecorator loginFailedDecorator) {
		this.objectMapper = objectMapper;
		this.cerberusLoginReturnProperties = cerberusLoginReturnProperties;
		this.loginFailedDecorator = loginFailedDecorator;
	}

	@Override
	public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException exception) throws IOException, ServletException {
		var result = loginFailedDecorator.decorate(request, response, exception);
		response.setStatus(HttpStatus.UNAUTHORIZED.value());
		response.setContentType(CONTENT_TYPE);
		response.setStatus(cerberusLoginReturnProperties.getFailedHttpStatus().value());
		response.getWriter()
				.write(objectMapper.writeValueAsString(SecureResponseEnum.LOGIN_FAIL.createSecureModel(
						cerberusLoginReturnProperties.getFailedMessageStatus(),
						exception instanceof CerberusAuthenticationException ? exception.getMessage()
								: cerberusLoginReturnProperties.getFailedMessage(),
						result)));
		response.flushBuffer();
	}
}
